from __future__ import absolute_import
import logging
import json
from django.utils import timezone
from django.db.models import Sum, Q
from django_redis import get_redis_connection
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from monitor.models import MonitorRealTimeInfo, MonitorAlarm, SceneDataMonitor, EmulationDetails, \
    EmulationDataMonitor, TrainDataDetails, TrainDataMonitor, AnnotateDataMonitor, OriginalDataMonitor, \
    TotalDataMonitor, AnnotateVendorDetails
from monitor.serializer import TotalDataMonitorSerializer, AnnotateDataMonitorSerializer, TrainDataMonitorSerializer, \
    EmulationDataMonitorSerializer

from common.tools import auth_request
from common.ploto_enum import CommonStatuEnum
from common.ploto_response import PlotoResponse

logger = logging.getLogger(__name__)
conn = get_redis_connection("default")


class AdministratorCheck(APIView):

    @auth_request
    def get(self, request):
        """
        获取总的数据量信息
        param request
        1、获取对应的数据obj段
        """
        if request.user.has_perm('monitor.Admin_TotalData'):
            return Response({'msg': 'you get Admin manage permission.'}, status=status.HTTP_200_OK)
        else:
            return Response({'msg': 'you do not have Admin manage permission.'}, status=status.HTTP_403_FORBIDDEN)


class TotalDataDisplay(APIView):

    @auth_request
    def get(self, request):
        """
        获取总的数据量信息
        param request
        1、获取对应的数据obj段
        """
        response = PlotoResponse()
        data = conn.hget("summarize_data", "data")
        if data is not None:
            response.data = json.loads(data)
            return Response(response.dict, status=status.HTTP_200_OK)
        obj = TotalDataMonitor.objects.get()
        serializer = TotalDataMonitorSerializer(obj)
        response_data = serializer.data
        response.data = response_data
        resp = conn.hmset("summarize_data", {"data": json.dumps(response_data), "isdelete": 0})
        conn.expire("summarize_data", 3600)
        if not resp:
            logger.error("总览数据缓存失败")
        return Response(response.dict, status=status.HTTP_200_OK)


class OriginalDataDisplay(APIView):
    display_key_field_list = ['area', 'graph_business']
    display_field_list = ['size', 'duration', 'mileage']

    @auth_request
    def get(self, request):
        """
        获取原始数据
        :param request:
        :return:
        """
        response = PlotoResponse()
        params = request.query_params.dict()
        display_key_field = params.get('display_field', 'area')
        if display_key_field not in self.display_key_field_list:
            response.msg = CommonStatuEnum.VALID_EXCEPTION.msg
            response.code = CommonStatuEnum.VALID_EXCEPTION.code
            return Response(response.dict, status=status.HTTP_400_BAD_REQUEST)
        data = conn.hget(f"{display_key_field}_original_data", "data")
        if data is not None:
            response.data = json.loads(data)
            return Response(response.dict, status=status.HTTP_200_OK)
        query_field = params.get(f'query_{display_key_field}', '')
        default_response_data = OriginalDataMonitor.objects.filter(**{display_key_field: query_field}) \
            if query_field else OriginalDataMonitor.objects
        sum_fields = {field: Sum(field) for field in self.display_field_list}
        response_data = list(default_response_data.values(display_key_field).annotate(**sum_fields))
        response.data = response_data
        resp = conn.hmset(f"{display_key_field}_original_data", {"data": json.dumps(response_data), "isdelete": 0})
        conn.expire(f"{display_key_field}_original_data", 3600)
        if not resp:
            logger.error("待脱敏数据缓存失败")
        return Response(response.dict, status=status.HTTP_200_OK)


class AnnotateDataDisplay(APIView):

    @auth_request
    def get(self, request):
        """
        获取汇总标注数据
        :param request:
        :return:
        """
        response = PlotoResponse()
        data = conn.hget("annotate_data", "data")
        if data is not None:
            response.data = json.loads(data)
            return Response(response.dict, status=status.HTTP_200_OK)
        obj = AnnotateDataMonitor.objects.get()
        serializer = AnnotateDataMonitorSerializer(obj)
        response_data = serializer.data
        response.data = response_data
        resp = conn.hmset("annotate_data", {"data": json.dumps(response_data), "isdelete": 0})
        conn.expire("annotate_data", 3600)
        if not resp:
            logger.error("汇总标注数据缓存失败")
        return Response(response.dict, status=status.HTTP_200_OK)


class AnnotateDataDetails(APIView):

    @auth_request
    def get(self, request):
        """
        获取标注数据详情
        :param request:
        :return:
        """
        response = PlotoResponse()
        params = request.query_params.dict()
        query_time = params.get('query_time', '')
        if not query_time:
            data = conn.hget("annotate_data_details", "data")
            if data is not None:
                response.data = json.loads(data)
                return Response(response.dict, status=status.HTTP_200_OK)
            else:
                response_data = AnnotateVendorDetails.objects.all().values('id', 'annotate_vendor', 'annotate_data',
                                                                           'annotate_number')
                response_data = list(response_data)
                response.data = response_data
                resp = conn.hmset("annotate_data_details", {"data": json.dumps(response_data), "isdelete": 0})
                conn.expire("annotate_data_details", 3600)
                if not resp:
                    logger.error("标注数据详情缓存失败")
                return Response(response.dict, status=status.HTTP_200_OK)
        if query_time:
            query_list = ['id', 'annotate_vendor', 'annotate_data', 'annotate_number']
            response_data = _get_by_time(query_time, AnnotateVendorDetails, query_list)
            response.data = {'data': response_data}
        return Response(response.dict, status=status.HTTP_200_OK)


class TrainDataDisplay(APIView):

    @auth_request
    def get(self, request):
        """
        获取训练数据
        :param request:
        :return:
        """
        response = PlotoResponse()
        data = conn.hget("train_data", "data")
        if data is not None:
            response.data = json.loads(data)
            return Response(response.dict, status=status.HTTP_200_OK)
        obj = TrainDataMonitor.objects.get()
        serializer = TrainDataMonitorSerializer(obj)
        response_data = serializer.data
        response.data = response_data
        resp = conn.hmset("train_data", {"data": json.dumps(response_data), "isdelete": 0})
        conn.expire("train_data", 3600)
        if not resp:
            logger.error("训练数据缓存失败")
        return Response(response.dict, status=status.HTTP_200_OK)


class TrainTaskDetails(APIView):

    @auth_request
    def get(self, request):
        """
        获取标注数据详情
        :param request:
        :return:
        """
        response = PlotoResponse()
        data = conn.hget("train_task_data", "data")
        if data is not None:
            response.data = json.loads(data)
            return Response(response.dict, status=status.HTTP_200_OK)
        obj = TrainDataDetails.objects.all().values()
        response_data = list(obj)
        response.data = response_data
        resp = conn.hmset("train_task_data", {"data": json.dumps(response_data), "isdelete": 0})
        conn.expire("train_task_data", 3600)
        if not resp:
            logger.error("训练数据详情缓存失败")
        return Response(response.dict, status=status.HTTP_200_OK)


class EmulationDataDisplay(APIView):

    @auth_request
    def get(self, request):
        """
        获取仿真
        :param request:
        :return:
        """
        response = PlotoResponse()
        data = conn.hget("emulation_data", "data")
        if data is not None:
            response.data = json.loads(data)
            return Response(response.dict, status=status.HTTP_200_OK)
        obj = EmulationDataMonitor.objects.get()
        serializer = EmulationDataMonitorSerializer(obj)
        response_data = serializer.data
        response.data = response_data
        resp = conn.hmset("emulation_data", {"data": json.dumps(response_data), "isdelete": 0})
        conn.expire("emulation_data", 3600)
        if not resp:
            logger.error("仿真数据缓存失败")
        return Response(response.dict, status=status.HTTP_200_OK)


class EmulationDataDetails(APIView):

    @auth_request
    def get(self, request):
        """
        获取标注数据详情
        :param request:
        :return:
        """
        response = PlotoResponse()
        params = request.query_params.dict()
        query_time = params.get('query_time', '')
        if not query_time:
            data = conn.hget("emulation_data_details", "data")
            if data is not None:
                response.data = json.loads(data)
                return Response(response.dict, status=status.HTTP_200_OK)
            else:
                response_data = EmulationDetails.objects.values('segmentation_scene').annotate(
                    subcategory_number=Sum('completed_tasks'))
                response_data = list(response_data)
                response.data = response_data
                resp = conn.hmset("emulation_data_details", {"data": json.dumps(response_data), "isdelete": 0})
                conn.expire("emulation_data_details", 3600)
                if not resp:
                    logger.error("仿真数据详情缓存失败")
                return Response(response.dict, status=status.HTTP_200_OK)
        if query_time:
            query_list = ['segmentation_scene']
            response_data = _get_by_time(query_time, EmulationDetails, query_list, 'completed_tasks')
            response.data = {'data': response_data}
        return Response(response.dict, status=status.HTTP_200_OK)


class SceneDataDisplay(APIView):

    @auth_request
    def get(self, request):
        """
        获取场景数据
        :param request:
        :return:
        """
        response = PlotoResponse()
        data = conn.hget("scene_data", "data")
        if data is not None:
            response.data = json.loads(data)
            return Response(response.dict, status=status.HTTP_200_OK)
        response_data = SceneDataMonitor.objects.values('main_scene').annotate(total_size=Sum('size'))
        response_data = list(response_data)
        response.data = response_data
        resp = conn.hmset("scene_data", {"data": json.dumps(response_data), "isdelete": 0})
        conn.expire("scene_data", 3600)
        if not resp:
            logger.error("场景数据缓存失败")
        return Response({'data': response_data}, status=status.HTTP_200_OK)


class SceneDataDetails(APIView):

    @auth_request
    def get(self, request):
        """
        获取标注数据详情
        :param request:
        :return:
        """
        response = PlotoResponse()
        params = request.query_params.dict()
        query_time = params.get('query_time', '')
        if not query_time:
            data = conn.hget("scene_data_details", "data")
            if data is not None:
                response.data = json.loads(data)
                return Response(response.dict, status=status.HTTP_200_OK)
            else:
                response_data = SceneDataMonitor.objects.values('scenario_id', 'main_scene').annotate(
                    subcategory_number=Sum('scenario_number'))
                response_data = list(response_data)
                response.data = response_data
                resp = conn.hmset("scene_data_details", {"data": json.dumps(response_data), "isdelete": 0})
                conn.expire("scene_data_details", 3600)
                if not resp:
                    logger.error("场景数据详情缓存失败")
                return Response({'data': response_data}, status=status.HTTP_200_OK)
        if query_time:
            query_list = ['scenario_id', 'main_scene']
            response_data = _get_by_time(query_time, SceneDataMonitor, query_list, 'scenario_number')
            response.data = {'data': response_data}
        return Response(response.dict, status=status.HTTP_200_OK)


class MonitorAlarmDisplay(APIView):

    @auth_request
    def get(self, request):
        response = PlotoResponse()
        data = conn.hget("monitor_alarm", "data")
        if data is not None:
            response.data = json.loads(data)
            return Response(response.dict, status=status.HTTP_200_OK)
        response_data = MonitorAlarm.objects.filter(level=0, is_delete=0).values('alarm_content', 'alarm_details')[:3]
        response_data = list(response_data)
        response.data = response_data
        resp = conn.hmset("monitor_alarm", {"data": json.dumps(response_data), "isdelete": 0})
        conn.expire("monitor_alarm", 3600)
        if not resp:
            logger.error("告警数据缓存失败")
        return Response(response.dict, status=status.HTTP_200_OK)


class MonitorNewsDisplay(APIView):

    @auth_request
    def get(self, request):
        response = PlotoResponse()
        data = conn.hget("monitor_news", "data")
        if data is not None:
            response.data = json.loads(data)
            return Response(response.dict, status=status.HTTP_200_OK)
        response_data = MonitorRealTimeInfo.objects.order_by("create_time").filter(is_delete=0).values(
            'region', 'info_content')[:5]
        response_data = list(response_data)
        response.data = response_data
        resp = conn.hmset("monitor_news", {"data": json.dumps(response_data), "isdelete": 0})
        conn.expire("monitor_news", 3600)
        if not resp:
            logger.error("大屏信息数据缓存失败")
        return Response(response.dict, status=status.HTTP_200_OK)


def _get_by_time(query_time, models, query_list, sum_field=None):
    cur_time = timezone.now()
    response_data = ""
    if query_time == "本周":
        # 获取本周的起始时间及结束时间
        start = (cur_time - timezone.timedelta(days=cur_time.weekday())).replace(hour=0, minute=0, second=0,
                                                                                 microsecond=0)
        end = (start + timezone.timedelta(days=7)).replace(hour=0, minute=0, second=0, microsecond=0)
        response_data = models.objects.filter(complete_time__range=(start, end)).values(
            *query_list)
        if sum_field:
            response_data = response_data.annotate(subcategory_number=Sum(sum_field))
    elif query_time == "本月":
        response_data = models.objects.filter(
            Q(complete_time__year=cur_time.year) & Q(complete_time__month=cur_time.month)).values(
            *query_list)
        if sum_field:
            response_data = response_data.annotate(subcategory_number=Sum(sum_field))
    return response_data
